﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Threading;
using MESHTTP;
using System.Diagnostics;
namespace FactoryApp
{
    public partial class WinForm : Form
    {
        private float X;
        private float Y;
        byte[] order = new byte[2];
        int portLength = 0;//串口的数量
        string strPort = null;//用于保存超声波串口
        string path = ".\\getPort.txt";//设置扫码枪串口文件
        Int16 MaxValue = 0;//串口接收数据的最大值（sp）
        Int16 minValue = 0;//串口数据的最小值
        int orFirst = 0;//用于判断是否是接收到的第一个数据
        SerialPort sp = new SerialPort();
        Thread threadBar = null;
        int actualHeightMin = 0;//用于设置超声波比较的范围数值
        int actualHeightMax = 0;
        bool isLengthChange = false;//串口数量是否改变
        Int16 ultrasonic = 0;  //用于保存接收到的超声波数据
        string[] information = new string[5];
        String serveEdition = null;//保存文件版本
        int setTime = 0;//定时上传时间设置
        string maxPort = null;//记住最大的窗口值
        Int16 maxPortValue = 0;//记忆最大的窗口号用于比较
        bool winstate = false;//初始状态为未打开状态
        bool isOpenStart = false;//用于显示是否开始测试
        System.Diagnostics.Process p = null;
        Int16 compareData = 0;
        public WinForm()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
            //this.DoubleBuffered = true; //控件缓冲，避免闪烁
            //this.SetStyle(ControlStyles.ResizeRedraw, true);
        }        
        private void WinForm_Load(object sender, EventArgs e)
        {
            this.Resize += new EventHandler(Winform_Resize);//窗体调整大小时引发事件
            X = this.Width;//获取窗体的宽度
            Y = this.Height;//获取窗体的高度
            setTag(this);//调用方法
            order[0] = 0xa5; //初始化超声波命令
            order[1] = 0x5a;

            #region 串口初始化
            //string[] Ports = null;
            //Ports = SerialPort.GetPortNames();
            //if (Ports.Length > 0)
            //{
            //    portLength = Ports.Length;
            //    foreach (string item in Ports)
            //    {
            //        cboxSerialPort.Items.Add(item);
            //    }
            //}
            #endregion

            #region 波特率初始化
            cboxBaudDate.Items.Add("2400");
            cboxBaudDate.Items.Add("4800");
            cboxBaudDate.Items.Add("9600");
            cboxBaudDate.Items.Add("115200");
            cboxBaudDate.Items.Add("256000");
            cboxBaudDate.Text = "256000";
            #endregion

            #region 串口属性初始化（数据位和校验位、停止位）
            sp.DataBits = 8;
            sp.StopBits = StopBits.One;
            sp.Parity = Parity.None;
            #endregion

            //初始化扫码抢的线程
            threadBar = new Thread(GetBarPort);
            threadBar.IsBackground = true;
            threadBar.Start();

            #region 读取文件中第一行的烧录软件程序路径 第二行是操作员 第三行是最小值，第四行是最大值 
            int i = 0;
            string line = null;
            FileStream fileStream = new FileStream(path, FileMode.Open);
            StreamReader sr = new StreamReader(fileStream,Encoding.Default);//必须指定读取的格式是Encoding.Default,要不然读取到的汉字是乱码
            while ((line = sr.ReadLine()) != null)
            {
                information[i] = line;
                ++i;
            }
            serveEdition = information[0];
            txtOperatorPerson.Text = information[1];
            actualHeightMin = Convert.ToInt32(information[2]);
            actualHeightMax = Convert.ToInt32(information[3]);
            //初始化最大值 最小值
            txtHightMin.Text = information[2];
            txtHeightMax.Text = information[3];
            //初始化定时设置
            txtTime.Text = information[4];
            setTime = Convert.ToInt32(information[4]);
            #endregion

        }
        #region 控件区
        private void btnOpenSerialPort_Click(object sender, EventArgs e)
        {
            if (cboxSerialPort.Text == "") MessageBox.Show("串口号不能为空！", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else if (cboxBaudDate.Text == "") MessageBox.Show("串口波特率不能为空！", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
            {
                if (btnOpenSerialPort.Text == "打开串口")
                {
                    strPort = cboxSerialPort.Text;//把当前串口名称传递给str
                    sp.PortName = cboxSerialPort.Text.Trim();
                    sp.BaudRate = Convert.ToInt32(cboxBaudDate.Text.Trim());
                    try
                    {
                        sp.Open(); //打开串口
                        DisplayMsg("串口打开成功");
                        sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
                        btnOpenSerialPort.Text = "关闭串口";
                        //不可修改波特率和串口数值
                        cboxSerialPort.Enabled = false;
                        cboxBaudDate.Enabled = false;
                    }
                    catch (Exception ex)
                    {
                        sp.Close();
                        MessageBox.Show("串口打开失败，具体原因：" + ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);

                    }
                }
                else
                {
                    if (btnStart.Text == "停止测试")
                    {
                        try
                        {
                            sp.Write(order, 1, 1);//关闭超声波
                            time1.Stop();
                            time_pbar.Stop();
                            MessageBox.Show("超声波关闭成功", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        catch
                        {
                            MessageBox.Show("无法关闭超声波", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                        btnStart.Text = "开始测试";
                        orFirst = 0;      //初始化最大最小值状态
                        minValue = 0;
                        MaxValue = 0;
                    }
                    try
                    {
                        btnOpenSerialPort.Text = "打开串口";
                        sp.Close();//关闭串口
                        DisplayMsg("串口关闭成功");
                        cboxSerialPort.Enabled = true;
                        cboxBaudDate.Enabled = true;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("串口关闭失败，具体原因：" + ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }

            }
        }  //打开串口设置
        private void btnStart_Click(object sender, EventArgs e)
        {
            if (!sp.IsOpen) DisplayMsg("串口未打开,此操作无效");/*MessageBox.Show("无效操作", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);*/
            else if((txtOperatorPerson.Text=="")|(txtSn.Text =="")) MessageBox.Show("操作员和SN码不能为空", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            else
            {
                if (btnStart.Text == "开始测试")
                {
                    isOpenStart = true;
                    orFirst = 0;
                    minValue = 0;
                    MaxValue = 0;
                    lblTextMax.Text = "0";
                    lblTestMin.Text = "0";
                    lblCurrentData.Text = "0";
                    txtUltrasonicEdi.Text = "";
                    pbarCountTime.Value = 1;
                    txtTime.Enabled = false;//禁止修改时间设置
                    try
                    {
                        sp.Write(order, 0, 1);
                        btnStart.Text = "停止测试";
                        DisplayMsg("超声波开始指令发送成功");
                        time1.Start();
                        time_pbar.Start();
                        DisplayMsg("---计时开始！---");
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("打开超声波指令传送失败：" + ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
            }
        }
        private void txtHight_TextChanged(object sender, EventArgs e) //实际高度数据改变
        {
            if (txtHightMin.Text.Trim() == "") return;
            else
            {
                actualHeightMin = Convert.ToInt32(txtHightMin.Text.Trim());
            }

        }
        private void txtHeightMax_TextChanged(object sender, EventArgs e) //测试允许的最大值范围
        {
            if (txtHeightMax.Text.Trim() == "") return;
            else
            {
                actualHeightMax = Convert.ToInt32(txtHeightMax.Text.Trim());
            }
        }
        private void btnDownLoad_Click(object sender, EventArgs e)
        {
            p = new System.Diagnostics.Process();
            p.StartInfo = new System.Diagnostics.ProcessStartInfo(@".\JFlash\JFlash.exe");
            p.EnableRaisingEvents = true;    //一定要有这个才能触发Exited 事件
            p.Exited += new EventHandler(p_Exited);
            if (winstate == false)
            {
                p.Start();
                winstate = true;
                
            }
            else
            {         
                
            }                      
        }  //下载固件
        private void WinForm_FormClosed(object sender, FormClosedEventArgs e) //窗体关闭程序
        {
            //把数据写入到information数组里面去
            information[1] = txtOperatorPerson.Text;
            information[2] = txtHightMin.Text;
            information[3] = txtHeightMax.Text;
            FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write);
            StreamWriter sr = new StreamWriter(fs, Encoding.Default);//必须指定读取的格式是Encoding.Default,要不然读取到的汉字是乱码
            for (int i = 0; i < information.Length; i++)
            {
                sr.WriteLine(information[i]);
            }
            sr.Close();
            fs.Close();
            if (winstate == true)
            {
                p.Kill();//关闭外部程序
            }

        }
        private void time1_Tick(object sender, EventArgs e) //定时时间自动上传
        {
            if (btnStart.Text == "停止测试")
            {
                try
                {
                    isOpenStart = false;
                    time1.Stop();//计时结束 
                    time_pbar.Stop();
                    txtTime.Enabled = true;//禁止修改时间设置
                    sp.Write(order, 1, 1);
                    btnStart.Text = "开始测试";
                    DisplayMsg("超声波停止指令发送成功");
                    compareData = Convert.ToInt16(lblTextMax.Text.Trim());
                    if (ToCompareData(compareData))
                    {
                        pbTestColor.BackColor = Color.Green;
                        //超声波版本信息比对
                        if (txtUltrasonicEdi.Text == "")
                        {
                            txtUltrasonicEdi.ForeColor = Color.Red;
                            txtUltrasonicEdi.Text = "无超声波版本数据";
                        }
                        else if (txtUltrasonicEdi.Text == serveEdition) txtUltrasonicEdi.ForeColor = Color.Blue;
                        else if (txtUltrasonicEdi.Text != serveEdition) txtUltrasonicEdi.ForeColor = Color.Red;
                        UpdataToMes(txtSn.Text, txtOperatorPerson.Text, true, "1");
                        MessageBox.Show("此料合格", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);                        
                    }
                    else
                    {
                        pbTestColor.BackColor = Color.Red;
                        //超声波版本信息比对
                        if (txtUltrasonicEdi.Text == "")
                        {
                            txtUltrasonicEdi.ForeColor = Color.Red;
                            txtUltrasonicEdi.Text = "无超声波版本数据";
                        }
                        else if (txtUltrasonicEdi.Text == serveEdition) txtUltrasonicEdi.ForeColor = Color.Blue;
                        else if (txtUltrasonicEdi.Text != serveEdition) txtUltrasonicEdi.ForeColor = Color.Red;
                        UpdataToMes(txtSn.Text, txtOperatorPerson.Text, false, "1");
                        MessageBox.Show("此料不合格", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        
                    }
                    txtSn.Focus();
                    txtSn.SelectAll();

                }
                catch (Exception ex)
                {
                    MessageBox.Show("关闭超声波指令传送失败：" + ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }

            }
        }
        private void txtTime_TextChanged(object sender, EventArgs e)//时间设置改变
        {
            if (txtTime.Text == "") return;
            setTime = Convert.ToInt32(txtTime.Text.Trim());//设置时间
            time1.Interval = setTime * 1000;//间隔以毫秒为单位
            pbarCountTime.Maximum = setTime;//设置进度条的最大值
            pbarCountTime.Value = 0;
        }
        private void time_pbar_Tick(object sender, EventArgs e)
        {
            ++pbarCountTime.Value;
        } //进度条定时触发事件
        #endregion 

        #region 自定义事件
        private void p_Exited(object sender, EventArgs e)
        {
            winstate = false;
        }
        private void Winform_Resize(object sender, EventArgs e)
        {
            float newx = (this.Width) / X;//窗体宽度缩放比例
            float newy = (this.Height) / Y;//窗体高度缩放比例
            setControls(newx, newy, this);//随窗体改变控件大小
            //this.Text = this.Width.ToString() + "" + this.Height.ToString();//窗体标题栏文本
        }
        private bool ToCompareData(Int16 datMax) //用于判断数据是否在规定的范围内
        {          
            bool istestOk = true;
            if ((datMax <= actualHeightMax) && (datMax >= actualHeightMin))
            {            
                istestOk = true;
            }
            else
            {
                istestOk = false;
            }
            return istestOk;
        }
        private void UpdataToMes(string sn, string name, bool good, string station)
        {
            string content = null;
            if (good == true)
            {
                content = "/rest/wip/bool/Test/string/" + sn + "/string/" + name + "/int64/" + station + "/string//string//string//rest";
            }
            else
            {
                content = "/rest/wip/bool/Test/string/" + sn + "/string/" + name + "/int64/" + station + "/string/FH001,,1/string//string//rest";
            }
            // string content = "/rest/wip/bool/Test/string/"+sn+"/string/"+name+"/int64/1/string/FH001,,1/string//string//rest";
            DisplayMsg(httpPost.PostRequest("http://120.197.116.82:9000", content)); //显示上传信息的状态
            //++number;
            //DisplayMsg("第" + "-" + number.ToString() + "-" + "数据上传成功");
        }  //上传数据到MES
        private void GetBarPort()
        {
            string[] BarPorts = null;
            while (true)
            {
                try
                {
                    BarPorts = SerialPort.GetPortNames();
                }
                catch
                {
                    DisplayMsg("串口异常，请重新打开串口");
                    btnOpenSerialPort.Text = "打开串口";
                    cboxSerialPort.Enabled = true;
                    cboxBaudDate.Enabled = true;
                    //串口打开以后 拔掉串口再次插上就会报错
                }
                if (BarPorts.Length > 0)
                {
                    if (portLength != BarPorts.Length)
                    {
                        isLengthChange = true;
                        maxPortValue = 0;
                    }
                    if (isLengthChange)
                    {                      
                        cboxSerialPort.Items.Clear();
                        foreach (string item in BarPorts)
                        {
                            if (Convert.ToInt16(item.Substring(3, item.Length-3)) >= maxPortValue)
                            {
                                maxPortValue = Convert.ToInt16(item.Substring(3, item.Length - 3));
                                maxPort = item;
                            }                         
                            cboxSerialPort.Items.Add(item);
                        }
                        if(btnOpenSerialPort.Text=="打开串口") cboxSerialPort.Text = maxPort;//只有在打开串口的时候才能进行最大串口赋值
                        isLengthChange = false;
                    }
                    portLength = BarPorts.Length;
                }
                if (btnOpenSerialPort.Text == "关闭串口") //在打开串口时，如果出现拔掉串口，这关闭串口
                {
                    if (!sp.IsOpen)
                    {
                        try
                        {

                            sp.Close();
                            time1.Stop();
                            time_pbar.Stop();
                        }
                        catch
                        {
                            MessageBox.Show("无法关闭串口","系统提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
                        }                     
                        cboxSerialPort.Items.Remove(strPort);//从集合中移除不存在的端口                  
                        cboxSerialPort.Text = "";
                        btnOpenSerialPort.Text = "打开串口";
                        cboxSerialPort.Enabled = true;
                        cboxBaudDate.Enabled = true;
                        if (btnStart.Text == "停止测试")
                        {
                            btnStart.Text = "开始测试";
                        }
                        DisplayMsg("串口非正常断开，请重启串口！");
                    }
                }
            }
        }  //获取串口的实时情况
        private void DisplayMsg(string str) //操作日志显示函数
        {
            txtOperator.Text += str + "\r\n";
            txtOperator.SelectionStart = txtOperator.Text.Length; //设定光标位置
            txtOperator.ScrollToCaret(); //滚动到光标处
        }
        private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //Invoke会阻塞当前线程
            this.BeginInvoke((EventHandler)delegate
            {
                if (isOpenStart == true)
                {
                    try
                    {
                        Byte[] ReceiveData = new Byte[sp.BytesToRead];
                        sp.Read(ReceiveData, 0, ReceiveData.Length);
                        if (ReceiveData.Length > 7) //此判断是防止接收到空数据时出现索引超出范围
                        {
                            if ((ReceiveData[0] == 0xFF))
                            {
                                ultrasonic = (Int16)((ReceiveData[2] << 8) | (ReceiveData[1]));
                                lblCurrentData.Text = ultrasonic.ToString();//接收的数据显示到文本框
                                if (orFirst == 0)                               //接收到的第一个数据默认为最小的数据
                                {
                                    minValue = ultrasonic;
                                    MaxValue = ultrasonic;
                                    lblTestMin.Text = minValue.ToString();
                                    lblTextMax.Text = MaxValue.ToString();
                                    txtUltrasonicEdi.Text = ReceiveData[3].ToString() + "." + ReceiveData[4].ToString() + "." + ReceiveData[5].ToString();
                                    orFirst = 1;
                                }
                                else
                                {
                                    if (ultrasonic < minValue) //保存最小值
                                    {
                                        minValue = ultrasonic;
                                        lblTestMin.Text = minValue.ToString();

                                    }
                                    if (ultrasonic > MaxValue) //保存最大值
                                    {
                                        MaxValue = ultrasonic;
                                        lblTextMax.Text = MaxValue.ToString();//保存接收数据的最大值
                                                                              //if (MaxValue > actualHeight) MessageBox.Show("数据与实际高度大", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                                    }
                                }

                            }
                        }
                        sp.DiscardInBuffer();//丢失接收缓冲区的数据
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("数据接收事件出现错误，具体错误：" + ex.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }

                }

            }
            );
        }//数据接收事件
        private void setControls(float newx, float newy, Control cons)
        {
            //遍历窗体中的控件，重新设置控件的值
            foreach (Control con in cons.Controls)
            {
                string[] mytag = con.Tag.ToString().Split(new char[] { ':' });//获取控件的Tag属性值，并分割后存储字符串数组
                float a = Convert.ToSingle(mytag[0]) * newx;//根据窗体缩放比例确定控件的值，宽度
                con.Width = (int)a;//宽度
                a = Convert.ToSingle(mytag[1]) * newy;//高度
                con.Height = (int)(a);
                a = Convert.ToSingle(mytag[2]) * newx;//左边距离
                con.Left = (int)(a);
                a = Convert.ToSingle(mytag[3]) * newy;//上边缘距离
                con.Top = (int)(a);
                Single currentSize = Convert.ToSingle(mytag[4]) * newy;//字体大小
                con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
                if (con.Controls.Count > 0)
                {
                    setControls(newx, newy, con);
                }
            }
        }  //根据窗体放大而放大控件
        private void setTag(Control cons)
        {
            //遍历窗体中的控件
            foreach (Control con in cons.Controls)
            {
                con.Tag = con.Width + ":" + con.Height + ":" + con.Left + ":" + con.Top + ":" + con.Font.Size;
                if (con.Controls.Count > 0) setTag(con);
            }
        }  //获取所有空间的信息
        #endregion
    }
}
